package fr.inserm.um915.jimpute.model;

import java.util.HashMap;
import java.util.Map;

import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;

public class Marker implements Comparable<Marker>
	{
	public enum Population {afr_aaf,amr_aaf,asn_aaf,eur_aaf,afr_maf,amr_maf,asn_maf,eur_maf };
	
	private String name=null;
	private ChromPosition position=null;
	private String a0="?";
	private String a1="?";
	private Map<Population,Float> pop2Maf=new HashMap<Population,Float>(4);
	private byte genotypes[]=null;
	
	
	public static final TupleBinding<Marker> BINDING=new TupleBinding<Marker>()
		{
		private ChromPosition.Binding posBing=new ChromPosition.Binding();
		@Override
		public void objectToEntry(Marker o, TupleOutput out)
			{
			out.writeString(o.name);
			out.writeString(o.a0);
			out.writeString(o.a1);
			posBing.objectToEntry(o.position, out);
			out.writeByte(o.pop2Maf.size());
			for(Population p:o.pop2Maf.keySet())
				{
				out.writeByte((byte)p.ordinal());
				out.writeFloat(o.pop2Maf.get(p));
				}
			writeGenotypes(o,out);
			}
		protected void writeGenotypes(Marker o, TupleOutput out)
			{
			if(o.genotypes==null)
				{
				out.writeInt(0);
				return;
				}
			out.writeInt(o.genotypes.length);
		    	//out.write(o.genotypes,0,o.genotypes.length);
			}
			
		@Override
		public Marker entryToObject(TupleInput in) {
			Marker m=new Marker();
			m.name=in.readString();
			m.a0=in.readString();
			m.a1=in.readString();
			m.position=this.posBing.entryToObject(in);
			
			int n=in.readByte();
			for(int i=0;i< n;++i)
				{
				Population p=Population.values()[in.readByte()];
				Float freq= in.readFloat();
				m.pop2Maf.put(p,freq);
				}
			
			readGenotypes(m,in);
			return m;
			}
		
		protected void readGenotypes(Marker o, TupleInput in)
			{
			int n=in.readInt();
			o.genotypes=new byte[n];
			//in.read(o.genotypes,0,n);
			}
		
		};
	
	
	public String getName()
		{
		return name;
		}
	
	public ChromPosition getPosition()
		{
		return position;
		}
	
	public Map<Population,Float> getPopulationFrequencies()
		{
		return this.pop2Maf;
		}
	
	@Override
	public int compareTo(Marker o) {
		int i= position.compareTo(o.position);
		if(i!=0) return i;
		i= name.compareToIgnoreCase(o.name);
		if(i!=0) return i;
		return 0;
		}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + name.hashCode();
		result = prime * result + position.hashCode();
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Marker other = (Marker) obj;
		return name.equals(other.name) && position.equals(other.position);
		}

	@Override
	public String toString()
		{
		return name+" "+position;
		}

	void setName(String name) {
		this.name = name;
	}

	void setPosition(ChromPosition position) {
		this.position = position;
	}

	void setA0(String a0) {
		this.a0 = a0;
	}

	void setA1(String a1) {
		this.a1 = a1;
	}
	
	public String getA0()
		{
		return a0;
		}
	
	public String getA1()
		{
		return a1;
		}
	
	public byte[] getGenotypes()
		{
		return genotypes;
		}
	
	void setGenotypes(byte genotypes[])
		{
		this.genotypes = genotypes;
		}
	
	}
